<template>

  <div>
    <!--drag 拖曳上传，去掉就是正常的上传-->
    <el-upload
      action="#"
      :accept="upload.accept"
      :auto-upload="upload.autoUpload"
      :on-change="imageChange"
      multiple
      drag
      :on-remove="onRemove"
      :on-preview="preview"
      :on-exceed="handleExceed"
      :limit="upload.limit"
      :show-file-list="upload.showFileList"
      :list-type="upload.pictureCard"
      :class="{hide: upload.hideUploadAdd}"
      :file-list="upload.fileList">


      <!--拖曳上传的提示文字-->
      <div class="el-upload__text">将图片拖到此处，或<em>点击上传</em>或直接复制粘贴</div>
      <!--普通上传-->
      <i class="el-icon-plus"></i>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png/jpeg/gif文件</div>
    </el-upload>

    <!--预览部分-->
    <el-dialog :visible.sync="dialogVisible" :append-to-body="true">
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>

</template>

<script>

  export default {
    // 多图片上传组件，支持截图粘贴、支持图片的预览、拖曳上传(推荐)
    name: "MultiplePictureUploadScreenshot",
    // 父子组件传值
    props:{
      // 作用，是否监听复制粘贴，有时候一个页面有多个这样的页面，这个时候就只能有一个监听
      paste: {
        type: Boolean,
        required: false,
        // 默认开启复制粘贴,false 不开启粘贴
        default: true
      }
    },
    data(){
      return {
        // 是否预览
        dialogVisible: false,
        // 预览的URL地址
        dialogImageUrl: '',
        // 上传配置
        upload: {
          // 上传的文件
          fileList: [],
          // 关闭自动上传
          autoUpload: false,
          // 是否显示上传文件列表
          showFileList: true,
          // 限制的图片类型
          accept: ".jpg,.jpeg,.png,.gif",
          // 照片picture-card展示的方式
          pictureCard: 'picture-card',
          // 最多一次上传10张图片，这里实际没啥用，用来做后续扩展的
          limit: 10,
          // 是否隐藏添加框，当添加数量达到后隐藏继续添加的按钮
          hideUploadAdd: false,
        },
      }
    },
    methods: {
      /**
       * 点击文件列表中已上传的文件时的钩子，用于预览
       * @param file 当前文件
       */
      preview(file){
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      },
      /**
       * 监听粘贴
       * 2022年8月31日01:42:07 无法解决粘贴后的多次上传图片问题
       * @param event 复制事件
       */
      handlePaste(event){
        // @paste.native="handlePaste"
        // 上传文件>=限制个数时隐藏上传组件

        let items = event.clipboardData.items[0]
        if(items.type.includes('image')) {
          if (this.upload.fileList.length >= this.upload.limit) {
            // 每次手动关闭所有弹框,这样就只会有一个消息了
            // document.getElementsByClassName('el-message').length > 0
            // document.getElementsByClassName(‘el-notification’).length === 0
            // let doms = document.getElementsByClassName('el-message')[0]
            // if (doms !== undefined){
            //   console.log("有重复消息")
            //   return;
            // }
            this.$message.warning("图片最大只允许上传" + this.upload.limit + "张!");
            return
          }

          let blob = items.getAsFile()
          let objectURL = URL.createObjectURL(blob);
          // 添加到列表中
          this.upload.fileList.push({"name": blob.name, "url": objectURL, "raw": blob})
        }

        // 添加图片后，最后判断一次，进行隐藏添加框
        this.uploadHide()
      },

      /**
       * 每次选择文件都会触发函数，可以用来前端删除和添加照片
       */
      imageChange(file, fileList){
        const isLt20M = file.size / 1024 / 1024 < 20;
        if (!isLt20M) {
          this.$message.error("上传图片大小不能超过 20MB!");
          fileList.splice(-1, 1);
        } else {
          this.upload.fileList = fileList;
        }
        // 上传文件>=限制个数时隐藏上传组件
        this.uploadHide()
      },
      /**
       * 上传组件是否隐藏添加
       */
      uploadHide(){
        // 上传文件>=限制个数时隐藏上传组件
        if (this.upload.fileList.length >= this.upload.limit) {
          this.upload.hideUploadAdd = true;
        } else {
          this.upload.hideUploadAdd = false;
        }
      },
      /**
       * 文件添加超过限制进行过滤
       * @param files
       * @param fileList
       */
      handleExceed(files, fileList) {
        this.$message.warning(`不能继续添加图片文件`);
      },
      /**
       * 文件列表移除文件时的钩子
       * 注意，这里的 fileList 是已经被处理过的数据，实际的 this.upload.fileList 里面的东西还没有被删除，这里很奇怪，如果是正常的上传走的逻辑，是会
       * 进行删除处理，复制的好像就不行
       */
      onRemove(file, fileList){
        // 使用 ES6 提供的 filter 方法，将fileList 中要删除的数据过滤掉，直接返回新的并赋值，等于删除了旧的图片文件
        this.upload.fileList = this.upload.fileList.filter(item => item.uid !== file.uid)
        // 上传文件>=限制个数时隐藏上传组件
        this.uploadHide()
      },
    },
    mounted(){
      if (this.paste){
        // 监听 ctrl+v键盘事件
        document.addEventListener ( 'paste' , (event)  =>  {
          // 阻止事件冒泡
          event.stopPropagation()
          this.handlePaste(event)
        });
      }
    }
  }
</script>

<style scoped>

</style>

<style >

  /*隐藏掉新的添加框，注意，要将style上传 scoped 去掉*/
  .hide .el-upload--picture-card {
    display: none;
  }

  /*拖曳上传的样式，比之前的框小很多*/
  .el-upload .el-upload-dragger {
    width: 250px;
    height: 150px;
  }
  .el-upload .el-upload-dragger .el-icon-upload {
    margin: 20px 0 16px;
  }

</style>
